<script setup>
import ConfigModal from "./components/ConfigModal.vue";
import PauseModal from "./components/PauseModal.vue";
import { ref, onMounted, onUnmounted } from "vue";

const canvas = ref(null);
const ctx = ref(null);
const isGameStarted = ref(false);
const isPaused = ref(false); // 暂停状态
const particles = ref([]); // 存储粒子数据（x,y坐标、速度、透明度）
const foodColor = ref("#FFD700"); // 食物颜色配置
const particleColor = ref("#FFD700"); // 粒子颜色配置
const snake = ref([{ x: 10, y: 10 }]);
const direction = ref("right");
const foods = ref([]); // 存储多个食物位置
const gameSpeed = ref(200);
const isConfigVisible = ref(false);
const highestScore = ref(0); // 最高分数

// 配置表单数据
const configForm = ref({
  speed: gameSpeed.value,
  count: 1,
  foodColor: foodColor.value,
  particleColor: particleColor.value,
});

// 初始化本地存储数据
const initLocalStorage = () => {
  const savedConfig = localStorage.getItem("snakeConfig");
  if (savedConfig) {
    const parsedConfig = JSON.parse(savedConfig);
    foodColor.value = parsedConfig.foodColor || "#FFD700";
    particleColor.value = parsedConfig.particleColor || "#FFD700";
    configForm.value.speed = parsedConfig.speed;
    configForm.value.count = parsedConfig.count;
    gameSpeed.value = parsedConfig.speed;
  }
  const savedScore = localStorage.getItem("snakeHighestScore");
  if (savedScore) highestScore.value = parseInt(savedScore);
};

// 显示配置弹窗
const showConfig = () => {
  configForm.value.speed = gameSpeed.value;
  configForm.value.count = configForm.value.count || 1; // 保持现有配置值
  isConfigVisible.value = true;
  document.body.style.overflow = "hidden"; // 弹窗显示时禁止滚动
};

// 保存配置
const saveConfig = () => {
  gameSpeed.value = configForm.value.speed;
  foodColor.value = configForm.value.foodColor;
  particleColor.value = configForm.value.particleColor;
  // 强制更新画布确保颜色立即生效
  if (ctx.value) draw();
  if (isGameStarted.value) generateFood(); // 游戏进行中时更新食物数量
  // 保存配置到本地存储
  localStorage.setItem(
    "snakeConfig",
    JSON.stringify({
      speed: configForm.value.speed,
      count: configForm.value.count,
      foodColor: configForm.value.foodColor,
      particleColor: configForm.value.particleColor,
    })
  );
  isConfigVisible.value = false;
};

// 关闭配置弹窗
const closeConfig = () => {
  isConfigVisible.value = false;
  document.body.style.overflow = "auto"; // 恢复滚动
};
let gameInterval = null;

// 初始化画布
const initCanvas = () => {
  ctx.value = canvas.value.getContext("2d");
  canvas.value.width = 800;
  canvas.value.height = 600;
  ctx.value.fillStyle = "#f0f0f0";
  ctx.value.fillRect(0, 0, 800, 600);
};

// 生成随机食物位置
// 生成指定数量的食物（根据配置）
const generateFood = () => {
  const newFoods = [];
  while (newFoods.length < configForm.value.count) {
    const newFood = {
      x: Math.floor(Math.random() * 40),
      y: Math.floor(Math.random() * 30),
    };
    // 检查新食物是否与蛇或已有食物位置重叠
    const isOverlap =
      snake.value.some(
        (segment) => segment.x === newFood.x && segment.y === newFood.y
      ) ||
      newFoods.some(
        (foodItem) => foodItem.x === newFood.x && foodItem.y === newFood.y
      );
    if (!isOverlap) newFoods.push(newFood);
  }
  foods.value = newFoods;
};

// 绘制游戏对象
const draw = () => {
  // 清空画布
  ctx.value.fillStyle = "#f0f0f0";
  ctx.value.fillRect(0, 0, 800, 600);

  // 绘制蛇
  ctx.value.fillStyle = "#000";
  snake.value.forEach((segment) => {
    ctx.value.fillRect(segment.x * 20, segment.y * 20, 20, 20);
  });

  // 绘制食物（支持多食物）
  ctx.value.fillStyle = foodColor.value; // 使用配置的食物颜色
  foods.value.forEach((foodItem) => {
    ctx.value.fillRect(foodItem.x * 20, foodItem.y * 20, 20, 20);
  });

  // 绘制粒子效果
  particles.value.forEach((particle, index) => {
    ctx.value.beginPath();
    ctx.value.arc(particle.x, particle.y, 2, 0, Math.PI * 2);
    ctx.value.fillStyle = `rgba(${parseInt(
      particleColor.value.slice(1, 3),
      16
    )}, ${parseInt(particleColor.value.slice(3, 5), 16)}, ${parseInt(
      particleColor.value.slice(5, 7),
      16
    )}, ${particle.alpha})`; // 使用配置的粒子颜色
    ctx.value.fill();
    // 更新粒子状态
    particle.x += particle.dx;
    particle.y += particle.dy;
    particle.alpha -= 0.05; // 加快透明度衰减使粒子更快消失
    if (particle.alpha <= 0) {
      particles.value.splice(index, 1);
    }
  });
};

// 移动蛇
const moveSnake = () => {
  const head = { ...snake.value[0] };

  switch (direction.value) {
    case "up":
      head.y--;
      break;
    case "down":
      head.y++;
      break;
    case "left":
      head.x--;
      break;
    case "right":
      head.x++;
      break;
  }

  // 碰撞检测（边界和自身）
  if (head.x < 0 || head.x >= 40 || head.y < 0 || head.y >= 30) {
    gameOver();
    return;
  }
  if (
    snake.value.some((segment) => segment.x === head.x && segment.y === head.y)
  ) {
    gameOver();
    return;
  }

  // 吃食物检测（支持多食物）
  const foodIndex = foods.value.findIndex(
    (foodItem) => head.x === foodItem.x && head.y === foodItem.y
  );
  if (foodIndex !== -1) {
    snake.value.unshift(head);
    foods.value.splice(foodIndex, 1); // 移除被吃掉的食物
    // 生成粒子效果（10个随机方向粒子）
    for (let i = 0; i < 10; i++) {
      const angle = Math.random() * Math.PI * 2; // 恢复360度全向扩散
      const speed = Math.random() * 5 + 2; // 降低速度缩小扩散范围
      particles.value.push({
        x: head.x * 20 + 10, // 食物中心x坐标
        y: head.y * 20 + 10, // 食物中心y坐标
        dx: Math.cos(angle) * speed,
        dy: Math.sin(angle) * speed,
        alpha: 1,
      });
    }
    if (foods.value.length === 0) generateFood(); // 所有食物被吃后生成新食物
  } else {
    snake.value.unshift(head);
    snake.value.pop();
  }
};

// 开始游戏
const startGame = () => {
  isGameStarted.value = true;
  snake.value = [{ x: 10, y: 10 }];
  direction.value = "right";
  generateFood(); // 根据当前配置生成初始食物
  draw(); // 初始绘制
  // 启动游戏循环
  // 优化游戏循环逻辑
  // 优化游戏循环逻辑
  const startGameLoop = () => {
    gameInterval = setInterval(() => {
      if (!isPaused.value) {
        moveSnake();
        draw();
      }
    }, gameSpeed.value);
  };

  // 启动游戏循环时重置暂停状态
  isPaused.value = false;
  startGameLoop();
};

// 游戏结束
const gameOver = () => {
  clearInterval(gameInterval);
  isGameStarted.value = false;
  const currentScore = snake.value.length - 1;
  // 更新最高分数
  if (currentScore > highestScore.value) {
    highestScore.value = currentScore;
    localStorage.setItem("snakeHighestScore", highestScore.value.toString());
  }
  alert(`游戏结束！得分：${currentScore}\n最高得分：${highestScore.value}`);
};

// 键盘事件处理
const handleKeyDown = (e) => {
  if (!isGameStarted.value) return;
  if (e.key === "Escape") {
    isPaused.value = !isPaused.value;
    return;
  }
  if (isPaused.value) return; // 暂停时忽略方向键
  switch (e.key) {
    case "ArrowUp":
      if (direction.value !== "down") direction.value = "up";
      break;
    case "ArrowDown":
      if (direction.value !== "up") direction.value = "down";
      break;
    case "ArrowLeft":
      if (direction.value !== "right") direction.value = "left";
      break;
    case "ArrowRight":
      if (direction.value !== "left") direction.value = "right";
      break;
  }
};

onMounted(() => {
  initCanvas();
  initLocalStorage(); // 初始化本地存储数据
  window.addEventListener("keydown", handleKeyDown);
});

onUnmounted(() => {
  window.removeEventListener("keydown", handleKeyDown);
});
</script>

<template>
  <div class="game-container">
    <div class="button-group">
      <button
        class="start-btn"
        @click="startGame"
        :disabled="isGameStarted"
        :class="{ disabled: isGameStarted }"
        :aria-disabled="isGameStarted"
        aria-label="开始游戏，已启动时禁用"
      >
        开始游戏
      </button>
      <button @click="showConfig" class="config-btn">游戏配置</button>
    </div>
    <canvas ref="canvas" class="game-canvas"></canvas>

    <ConfigModal
      :is-visible="isConfigVisible"
      @save="saveConfig"
      @close="closeConfig"
    />
  </div>
  <PauseModal :is-visible="isPaused" @close="() => (isPaused = false)" />
</template>

<style scoped>
/* 暂停弹窗样式 */
.pause-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1001;
}
.pause-box {
  background: white;
  padding: 30px 50px;
  border-radius: 15px;
  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
  text-align: center;
}
.pause-box h3 {
  color: #2c3e50;
  margin-bottom: 15px;
}
.pause-box p {
  color: #666;
  margin: 0;
}
/* 禁用按钮样式 */
.start-btn.disabled {
  background: #999;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
/* 全局重置滚动条 */
html,
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
}
/* 配置弹窗样式 */
.config-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.2);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.config-box {
  background: #ffffff;
  padding: 40px;
  border-radius: 18px;
  min-width: 450px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
  transform: translateY(-5px);
}

.config-box h3 {
  text-align: center;
  color: #2c3e50;
  margin-bottom: 25px;
}

.config-item {
  margin-bottom: 25px;
  display: flex;
  align-items: center;
  gap: 20px;
}

.config-item label {
  color: #34495e;
  font-weight: 500;
  min-width: 120px;
}

.config-item input {
  padding: 12px 16px;
  border: 1px solid #e8e8e8;
  border-radius: 8px;
  flex: 1;
  font-size: 16px;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05);
  transition: all 0.3s;
}
.config-item input:focus {
  border-color: #2c3e50;
  box-shadow: 0 0 0 2px rgba(44, 62, 80, 0.1);
  outline: none;
  background: #f9fafb;
}

.config-btns {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 25px;
}

.save-btn {
  padding: 12px 24px;
  background: #28a745;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 16px;
}

.cancel-btn {
  padding: 12px 24px;
  background: #dc3545;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 16px;
}

.save-btn:hover,
.cancel-btn:hover {
  transform: scale(1.05);
}
.game-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 80vh;
  padding-top: 30px;
  background-color: #f8f9fa;
  overflow: hidden;
}

.start-btn {
  padding: 14px 32px;
  font-size: 18px;
  font-weight: 600;
  color: #ffffff;
  background: linear-gradient(135deg, #28a745 0%, #218838 100%);
  border: none;
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 3px 8px rgba(40, 167, 69, 0.2);
}

.start-btn:hover {
  background-color: #218838;
  transform: scale(1.05);
}

.button-group {
  margin-bottom: 45px;
  display: flex;
  gap: 35px;
  justify-content: center;
  align-items: center;
}

.config-btn {
  padding: 14px 32px;
  background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
  color: white;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.5px;
  box-shadow: 0 3px 8px rgba(44, 62, 80, 0.2);
}
.config-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(44, 62, 80, 0.3);
  background: linear-gradient(135deg, #34495e 0%, #2c3e50 100%);
}
.config-btn:hover {
  background: #34495e;
}
.game-canvas {
  border: 2px solid #343a40;
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
</style>